package org.juggers.domain;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

/**
 * @author <a href="mailto:nicolas@breizhjug.org">Nicolas De loof</a>
 * @author <a href="mailto:michel@breizhjug.org">Michel DAVID</a>
 */
@Entity( name = "org.juggers.domain.Jugger" )
@Configurable
public class Jugger
    extends AbstractEntity
{

    private static final long serialVersionUID = -5940263587617471567L;

    /** Internal state */
    public static enum State
    {
        PENDING, REGISTERED;
    }

    @Autowired
    private transient TokenGenerator tokenGenerator;

    @Autowired
    private transient PasswordGenerator passwordGenerator;

    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    private Long id;

    private String firstName;

    private String lastName;

    private Date birthDate;

    private String eMail;

    private String password;

    private String pictureUrl;

    private Date creationDate;

    private Date confirmDate;

    private State state;

    private String registrationToken;
    
    private Set<String> roles = new HashSet<String>();

    public Jugger( String mail )
    {
        this();
        this.eMail = mail;
    }

    public Jugger()
    {
        super();
        this.creationDate = new Date();
    }

    public boolean isPending()
    {
        return state == State.PENDING;
    }

    public void setPending()
    {
        setState( State.PENDING );
    }

    public boolean isRegistered()
    {
        return state == State.REGISTERED;
    }

    /**
     * @param token
     */
    public void confirm( String token )
        throws AlreadyConfirmedException, InvalidTokenException
    {
        if ( state != State.PENDING )
        {
            throw new AlreadyConfirmedException();
        }
        if ( token.equals( registrationToken ) )
        {
            setState( State.REGISTERED );
        }
        else
        {
            throw new InvalidTokenException();
        }
    }

    private void setState( State state )
    {
        State oldValue = this.state;
        this.state = state;
        switch ( state )
        {
            case PENDING:
                this.registrationToken = tokenGenerator.createToken();
                this.password = passwordGenerator.createPassword();
                this.confirmDate = null;
                break;
            case REGISTERED:
            default:
                this.confirmDate = new Date();
                break;
        }
        firePropertyChange( "state", oldValue, state );
    }

    // --- JavaBean accessors ---

    /**
     * @return the id
     */
    public Long getId()
    {
        return this.id;
    }

    /**
     * @param id the id to set
     */
    public void setId( Long id )
    {
        Long oldValue = this.id;
        this.id = id;
        firePropertyChange( "id", oldValue, id );
    }

    /**
     * @return the firstName
     */
    public String getFirstName()
    {
        return this.firstName;
    }

    /**
     * @param firstName the firstName to set
     */
    public void setFirstName( String firstName )
    {
        String oldValue = this.firstName;
        this.firstName = firstName;
        firePropertyChange( "firstName", oldValue, firstName );
    }

    /**
     * @return the lastName
     */
    public String getLastName()
    {
        return this.lastName;
    }

    /**
     * @param lastName the lastName to set
     */
    public void setLastName( String lastName )
    {
        String oldValue = this.lastName;
        this.lastName = lastName;
        firePropertyChange( "lastName", oldValue, lastName );
    }

    /**
     * @return the birthDate
     */
    public Date getBirthDate()
    {
        return this.birthDate;
    }

    /**
     * @param birthDate the birthDate to set
     */
    public void setBirthDate( Date birthDate )
    {
        Date oldValue = this.birthDate;
        this.birthDate = birthDate;
        firePropertyChange( "birthDate", oldValue, birthDate );
    }

    /**
     * @return the eMail
     */
    public String getEMail()
    {
        return this.eMail;
    }

    /**
     * @param mail the eMail to set
     */
    public void setEMail( String mail )
    {
        String oldValue = this.eMail;
        this.eMail = mail;
        firePropertyChange( "eMail", oldValue, mail );
    }

    /**
     * @return the pictureUrl
     */
    public String getPictureUrl()
    {
        return this.pictureUrl;
    }

    /**
     * @param pictureUrl the pictureUrl to set
     */
    public void setPictureUrl( String pictureUrl )
    {
        String oldValue = this.pictureUrl;
        this.pictureUrl = pictureUrl;
        firePropertyChange( "pictureUrl", oldValue, pictureUrl );
    }

    public Date getCreationDate()
    {
        return creationDate;
    }

    public Date getConfirmDate()
    {
        return confirmDate;
    }

    public String getRegistrationToken()
    {
        return registrationToken;
    }

    public String getPassword()
    {
        return password;
    }

    public void setPassword( String password )
    {
        String oldValue = this.password;
        this.password = password;
        firePropertyChange( "password", oldValue, password );
    }
    
    public Set<String> getRoles()
    {
        return roles;
    }

    public void setRoles( Set<String> roles )
    {
        Set<String> oldValue = this.roles;
        this.roles = roles;
        firePropertyChange( "roles", oldValue, roles );
    }


    // Fonzie methods
    public native void persist() /*-{

    }-*/;

    public native void refresh() /*-{

    }-*/;

    public native Jugger merge() /*-{

    }-*/;

    public native void remove() /*-{

    }-*/;

    public native static Collection<Jugger> findAll() /*-{

    }-*/;

    public native static Jugger findByEMail( String eMail ) /*-{

    }-*/;
    
    public native static Jugger findById( Long id ) /*-{

    }-*/;
}
